package com.pdd.message.server.service.impl;

import com.alibaba.fastjson.JSON;
import com.corundumstudio.socketio.SocketIOServer;
import com.pdd.commons.entity.vo.AccountInfo_Vo;
import com.pdd.commons.entity.vo.Message_Vo;
import com.pdd.commons.utils.AccountUtil;
import com.pdd.commons.utils.RedisUtils;
import com.pdd.message.server.commons.config.BlogMessageListener;
import com.pdd.message.server.commons.consts.TCPServerConst;
import com.pdd.message.server.service.Blog_MessageService;
import com.pdd.message.server.service.SocketIOService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;

/**
 * @author:liyangpeng
 * @date:2019/7/30 10:15
 */
@Service
@Slf4j
public class SocketIOServiceImpl implements SocketIOService {

    @Autowired
    private SocketIOServer socketIOServer;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private AccountUtil accountUtil;
    @Autowired
    private Blog_MessageService blog_messageService;
    /**
     * Spring IoC容器创建之后，在加载SocketIOServiceImpl Bean之后启动
     * @throws Exception
     */
    @PostConstruct
    private void autoStartup() throws Exception {
        start();
    }
    /**
     * Spring IoC容器在销毁SocketIOServiceImpl Bean之前关闭,避免重启项目服务端口占用问题
     * @throws Exception
     */
    @PreDestroy
    private void autoStop() throws Exception  {
        stop();
    }
    /**
     * TCP服务监听
     * @throws Exception
     */
    @Override
    public void start() throws Exception {
        // 监听客户端连接
        socketIOServer.addConnectListener(client -> {
            log.info("有客户端加入链接：{}", JSON.toJSONString(client));
        });

        // 监听客户端断开连接
        socketIOServer.addDisconnectListener(client -> {
            log.info("有客户端断开链接：{}", JSON.toJSONString(client));
        });

        // 处理自定义的事件，与连接监听类似
        socketIOServer.addEventListener(RECEIVE_EVENT, Message_Vo.class, (client, data, ackSender) -> {
            List<String> tokens=client.getHandshakeData().getUrlParams().get("token");
            if(tokens!=null&&!tokens.isEmpty()){
                String token=tokens.get(0);
                AccountInfo_Vo accountInfo_vo=accountUtil.getUserInfoByToken(token);
                if(accountInfo_vo!=null){
                    log.info("RECEIVE_EVENT事件监听：client={}", JSON.toJSONString(client));
                    log.info("RECEIVE_EVENT事件监听：data={}", JSON.toJSONString(data));
                    log.info("RECEIVE_EVENT事件监听：ackSender={}", JSON.toJSONString(ackSender));
                    //redis订阅上自身的队列
                    redisUtils.subscribe(accountInfo_vo.getId()+ TCPServerConst.CLIENT_SUFFIX,new BlogMessageListener(client));
                    log.info("-----------RECEIVE_EVENT事件监听结束------------");
                    //拉取离线消息推送到客户端
                    Message_Vo message_vo=blog_messageService.sendUnreadMessage(accountInfo_vo);
                    if(message_vo!=null){
                        client.sendEvent(SocketIOService.PUSH_EVENT,message_vo);
                    }
                }
            }
        });
        socketIOServer.start();
    }
    /**
     * 服务停止
     */
    @Override
    public void stop() {
        if (socketIOServer != null) {
            socketIOServer.stop();
            socketIOServer = null;
        }
    }

}
